<?php
/**
* Copyright 2009 Waag Society <http://www.waag.org>
* This file is part of Annotrax.
*
* Annotrax is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* Annotrax is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Annotrax.
* If not, see http://www.gnu.org/licenses/gpl.html
*/
class Default_Model_AnnotationMapper extends At_Model_Mapper{
    protected $dbTable;
    protected $tableName = 'annotation';

    protected $limit;
    protected $offset;

	/**
	 * Find by properties: if an overlap is made by an annotation on the same channel
	 * That has the same start-point, the existing annotation will be updated instead!
	 *
	 * @param Default_Model_Annotation $annotation The annotation to be found
	 * @return void
	 */
	public function findByProperties( Default_Model_Annotation $annotation ){
		$db = $this->getTable()->getAdapter();

		$values = array(
			':movie_id'		=> $annotation->movieId,
			':channel_id'	=> $annotation->channelId,
			':time'			=> $annotation->time,
			':user_id'		=> $annotation->userId
		);

		$result = $this->getTable()->getAdapter()->fetchRow('
			SELECT *
			FROM annotation
			WHERE movie_id = :movie_id
			AND channel_id = :channel_id
			AND time = :time
			AND user_id = :user_id
		', $values
		);

		if( false !== $result && key_exists( 'id', $result ) ){
			foreach( $result as $key => $value ){
				$annotation->$key = $value;
			}
		}
	}

	/**
	 * Save or update annotation
	 *
	 * @param Default_Model_Annotation $annotation The annotation to save
	 * @return void
	 */
    public function save( Default_Model_Annotation $annotation ){
		$db = $this->getTable()->getAdapter();

		$values = array(
            'duration'      => $annotation->getDuration(false),
            'time'          => $annotation->getStart(false),
            'movie_id'      => $annotation->movieId,
            'channel_id'    => $annotation->channelId,
            'comment'       => $annotation->comment,
            'user_id'       => $annotation->userId
		);

		$id = $annotation->id;
		//var_dump( $id ); exit;

		$values = array_filter( $values );

		if( null === $id ){
			$annotation->id = $this->getTable()->insert( $values );
		}
		else{
            $this->getTable()->update( $values, array( 'id = ?' => $id ) );
        }

		$db->query('
			DELETE FROM annotation_keyword
			WHERE annotation_id = ?',
			$annotation->id
		);

		foreach( $annotation->getKeywords() as $keyword ){
			$values = array(
				'annotation_id'	=> $annotation->id,
				'keyword_id'	=> $keyword->id
			);

			$db->insert( 'annotation_keyword', $values );
		}
    }

	/**
	 * Delete annotation and remove references from keywords
	 *
	 * @param Default_Model_Annotation $annotation To delete
	 * @return void
	 */
    public function delete( Default_Model_Annotation $annotation ){
		$db = $this->getTable()->getAdapter();

		$db->query('
			DELETE a.*, ak.*
			FROM annotation a
			LEFT JOIN annotation_keyword ak ON ak.annotation_id = a.id
			WHERE a.id = ?
		', $annotation->id );
    }

	/**
	 * Fetch all annotations (that match $annotation's properties)
	 *
	 * @param Default_Model_Annotation $annotation Annotation. set properties such as userId to filter
	 * @return array $results
	 */
    public function fetchAll( Default_Model_Annotation $annotation ){
		$db      = $this->getTable();
		$collect = array();
		$where  = "";//array();

		if( null !== $annotation->movieId ){ //[LL]
			$where = sprintf("movie_id = %d", $annotation->movieId);
		}
		if( null !== $annotation->channelId ){
			if($where != "")
			{
				$where .= " AND ";
			}
			$where = sprintf("%s channel_id = %d", $where, $annotation->channelId);
		}
		if( null !== $annotation->userId ){
			if($where != "")
			{
				$where .= " AND ";
			}
			$where = sprintf("%s user_id = %d", $where, $annotation->userId);
		}
		
		$result = $db->fetchAll(
			$where,
			'time',
			( $annotation->getLimit() > 0 ? $annotation->getLimit() : null ),
			( $annotation->getOffset() > 0 ? $annotation->getOffset() : null )
		);

		foreach( $result as $values ){
			$collect[] = new Default_Model_Annotation( $values->toArray() );
		}

		return $collect;
    }

	/**
	 * Return the fetchCount for pager queryies (results that would be returned by fetchAll for limit 0)
	 *
	 * @param Default_Model_Annotation $annotation
	 * @return int $count
	 */
    public function fetchCount( Default_Model_Annotation $annotation ){
		$db      = $this->getTable()->getAdapter();
		$where   = array();
		$values  = array();

		if( null !== $annotation->movieId ){
			$where[] = 'movie_id = :movie_id';
			$values['movie_id'] = $annotation->movieId;
		}
		if( null !== $annotation->channelId ){
			$where[] = 'channel_id = :channel_id';
			$values['channel_id'] = $annotation->channelId;
		}
		if( null !== $annotation->userId ){
			$where[] = 'user_id = :user_id';
			$values['user_id'] = $annotation->userId;
		}

		$query = sprintf('
			SELECT COUNT(id) AS total
			FROM annotation
			WHERE ' . join( ' AND ', $where ) . '
			ORDER BY time ASC
		');

		$result = $db->fetchRow( $query, $values, Zend_Db::FETCH_OBJ );

		return $result->total;
    }
}
